/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.lang.Nullable;

/**
 * 通过拥有自动注入能力的bean工厂扩展了{@link BeanFactory}接口的能力,只要他们愿意的话,他们就可以暴露这个功能(自动注入).
 * <p>
 * 当然,这并不意味着在常规的应用代码中会使用到这个功能,对于这个功能的典型示范,可以参考{@link BeanFactory}和
 * {@link org.springframework.beans.factory.ListableBeanFactory}.
 * <p>
 * 其他框架在整合spring的时候,可以通过这个接口来填充管理生命周期不受spring控制的已有bean实例.
 * 比如,经典的框架webWork和Tapestry.
 * <p>
 * 需要注意的是,这个接口不是用{@link org.springframework.context.ApplicationContext}的门面模式实现的.因为在应用程序中,几乎不会
 * 用到他,不过,换句话来说,这也意味着他也能够从应用上下文中得到,
 * 通过{@link org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()}来获取.
 * <p>
 * 其实你也可以去实现{@link org.springframework.beans.factory.BeanFactoryAware}接口,因为在应用上下文运行的时候,他会暴露出内部的
 * BeanFactory,我们只需要将这个BeanFactory转换为AutowireCapableBeanFactory就可以获取到AutowireCapableBeanFactory了.
 * <p>
 * Extension of the {@link org.springframework.beans.factory.BeanFactory}
 * interface to be implemented by bean factories that are capable of
 * autowiring, provided that they want to expose this functionality for
 * existing bean instances.
 * <p>
 * <p>This sub-interface of BeanFactory is not meant to be used in normal
 * application code: stick to {@link org.springframework.beans.factory.BeanFactory}
 * or {@link org.springframework.beans.factory.ListableBeanFactory} for
 * typical use cases.
 * <p>
 * <p>Integration code for other frameworks can leverage this interface to
 * wire and populate existing bean instances that Spring does not control
 * the lifecycle of. This is particularly useful for WebWork Actions and
 * Tapestry Page objects, for example.
 * <p>
 * <p>Note that this interface is not implemented by
 * {@link org.springframework.context.ApplicationContext} facades,
 * as it is hardly ever used by application code. That said, it is available
 * from an application context too, accessible through ApplicationContext's
 * {@link org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()}
 * method.
 * <p>
 * <p>You may also implement the {@link org.springframework.beans.factory.BeanFactoryAware}
 * interface, which exposes the internal BeanFactory even when running in an
 * ApplicationContext, to get access to an AutowireCapableBeanFactory:
 * simply cast the passed-in BeanFactory to AutowireCapableBeanFactory.
 *
 * @author Juergen Hoeller
 * @see org.springframework.beans.factory.BeanFactoryAware
 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
 * @see org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()
 * @since 04.12.2003
 */
public interface AutowireCapableBeanFactory extends BeanFactory {

	/**
	 * 表示没有自动注入的常量,不过,需要注意的是,通过BeanFactoryAware和注释驱动的注入依然会被应用.
	 * <p>
	 * Constant that indicates no externally defined autowiring. Note that
	 * BeanFactoryAware etc and annotation-driven injection will still be applied.
	 *
	 * @see #createBean
	 * @see #autowire
	 * @see #autowireBeanProperties
	 */
	int AUTOWIRE_NO = 0;

	/**
	 * 表示按照名称来自动注入的常量.
	 * <p>
	 * Constant that indicates autowiring bean properties by name
	 * (applying to all bean property setters).
	 *
	 * @see #createBean
	 * @see #autowire
	 * @see #autowireBeanProperties
	 */
	int AUTOWIRE_BY_NAME = 1;

	/**
	 * 表示通过类型来依赖注入的常量.
	 * <p>
	 * Constant that indicates autowiring bean properties by type
	 * (applying to all bean property setters).
	 *
	 * @see #createBean
	 * @see #autowire
	 * @see #autowireBeanProperties
	 */
	int AUTOWIRE_BY_TYPE = 2;

	/**
	 * 表示通过构造函数来执行依赖注入的常量.
	 * <p>
	 * Constant that indicates autowiring the greediest constructor that
	 * can be satisfied (involves resolving the appropriate constructor).
	 *
	 * @see #createBean
	 * @see #autowire
	 */
	int AUTOWIRE_CONSTRUCTOR = 3;

	/**
	 * 表示通过对bean的反射来自动确定使用的注入方式.
	 * <p>
	 * Constant that indicates determining an appropriate autowire strategy
	 * through introspection of the bean class.
	 *
	 * @see #createBean
	 * @see #autowire
	 * @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
	 * prefer annotation-based autowiring for clearer demarcation of autowiring needs.
	 */
	@Deprecated
	int AUTOWIRE_AUTODETECT = 4;


	//-------------------------------------------------------------------------
	// 用于创建和填充外部bean实例的方法.
	// Typical methods for creating and populating external bean instances
	//-------------------------------------------------------------------------

	/**
	 * 创建指定类的完整bean实例.
	 * 执行bean的全部初始化方法,包括bean的后置处理器.
	 * 注意:这个方法是用来创建一个填充了带注释的字段和方法,以及应用了所有标准的bean初始化回调的bean的新实例,对于传统的按名称注入,按属性注入
	 * 来讲可以调用createBean(Class,int,boolean)方法.
	 * <p>
	 * Fully create a new bean instance of the given class.
	 * <p>Performs full initialization of the bean, including all applicable
	 * {@link BeanPostProcessor BeanPostProcessors}.
	 * <p>Note: This is intended for creating a fresh instance, populating annotated
	 * fields and methods as well as applying all standard bean initialization callbacks.
	 * It does <i>not</> imply traditional by-name or by-type autowiring of properties;
	 * use {@link #createBean(Class, int, boolean)} for those purposes.
	 *
	 * @param beanClass the class of the bean to create
	 * @return the new bean instance
	 * @throws BeansException if instantiation or wiring failed
	 */
	<T> T createBean(Class<T> beanClass) throws BeansException;

	/**
	 * 通过应用实例化后的bean回调函数以及bean属性后置处理器来填充指定的bean实例(例如,注解读取的注入).
	 * 注意,这个方法主要是为了重新填充带注解的字段和方法,应用场景是新实例和反序列化实例.
	 * 对于传统的按名称/属性自动装配还是需要调用autowireBeanProperties方法.
	 * <p>
	 * Populate the given bean instance through applying after-instantiation callbacks
	 * and bean property post-processing (e.g. for annotation-driven injection).
	 * <p>Note: This is essentially intended for (re-)populating annotated fields and
	 * methods, either for new instances or for deserialized instances. It does
	 * <i>not</i> imply traditional by-name or by-type autowiring of properties;
	 * use {@link #autowireBeanProperties} for those purposes.
	 *
	 * @param existingBean the existing bean instance
	 * @throws BeansException if wiring failed
	 */
	void autowireBean(Object existingBean) throws BeansException;

	/**
	 * 配置给定的原始bean:自动注入bean的属性,应用bean的属性值,使用工厂中类似setBeanName和setBeanFactory之类的回调方法.
	 * 同时应用所有的bean后处理器(包括可能用于装饰原始bean后置处理器).
	 * 这是一个initializeBean提供的一个超集,通过对应的bean定义来进行完整的配置.
	 * <p>
	 * Configure the given raw bean: autowiring bean properties, applying
	 * bean property values, applying factory callbacks such as {@code setBeanName}
	 * and {@code setBeanFactory}, and also applying all bean post processors
	 * (including ones which might wrap the given raw bean).
	 * <p>This is effectively a superset of what {@link #initializeBean} provides,
	 * fully applying the configuration specified by the corresponding bean definition.
	 * <b>Note: This method requires a bean definition for the given name!</b>
	 *
	 * @param existingBean the existing bean instance
	 * @param beanName     the name of the bean, to be passed to it if necessary
	 *                     (a bean definition of that name has to be available)
	 * @return the bean instance to use, either the original or a wrapped one
	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException if there is no bean definition with the given name
	 * @throws BeansException                                                  if the initialization failed
	 * @see #initializeBean
	 */
	Object configureBean(Object existingBean, String beanName) throws BeansException;


	//-------------------------------------------------------------------------
	// 用于对bean声明称进行细粒度控制的方法.
	// Specialized methods for fine-grained control over the bean lifecycle
	//-------------------------------------------------------------------------

	/**
	 * 通过指定的自动注入策略来创建一个给定类的完整的bean实例.这里支持当前接口定义的所有常量.
	 * 指定bean的全部初始化方法,包括bean后处理器,这是autowire提供的一个有效超集,增加了initializeBean的行为.
	 * <p>
	 * Fully create a new bean instance of the given class with the specified
	 * autowire strategy. All constants defined in this interface are supported here.
	 * <p>Performs full initialization of the bean, including all applicable
	 * {@link BeanPostProcessor BeanPostProcessors}. This is effectively a superset
	 * of what {@link #autowire} provides, adding {@link #initializeBean} behavior.
	 *
	 * @param beanClass       the class of the bean to create
	 * @param autowireMode    by name or type, using the constants in this interface
	 * @param dependencyCheck whether to perform a dependency check for objects
	 *                        (not applicable to autowiring a constructor, thus ignored there)
	 * @return the new bean instance
	 * @throws BeansException if instantiation or wiring failed
	 * @see #AUTOWIRE_NO
	 * @see #AUTOWIRE_BY_NAME
	 * @see #AUTOWIRE_BY_TYPE
	 * @see #AUTOWIRE_CONSTRUCTOR
	 */
	Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

	/**
	 * 通过指定的自动注入策略来给指定的class实例化一个新的实例.其支持所有当前接口定义的常量.
	 * 同时也可以AUTOWIRE_NO来仅执行Bean前处理器(例如基于注解驱动的注入).
	 * 他不会应用任何标准的Bean后处理器,或者执行当前bean的任何进一步的初始化方法.
	 * 该接口为了这个目的提供了不同的细粒度操作(比如:initializeBean).但是,如果使用了构造实例,
	 * 则会执行InstantiationAwareBeanPostProcessor的回调.
	 * <p>
	 * Instantiate a new bean instance of the given class with the specified autowire
	 * strategy. All constants defined in this interface are supported here.
	 * Can also be invoked with {@code AUTOWIRE_NO} in order to just apply
	 * before-instantiation callbacks (e.g. for annotation-driven injection).
	 * <p>Does <i>not</i> apply standard {@link BeanPostProcessor BeanPostProcessors}
	 * callbacks or perform any further initialization of the bean. This interface
	 * offers distinct, fine-grained operations for those purposes, for example
	 * {@link #initializeBean}. However, {@link InstantiationAwareBeanPostProcessor}
	 * callbacks are applied, if applicable to the construction of the instance.
	 *
	 * @param beanClass       the class of the bean to instantiate
	 * @param autowireMode    by name or type, using the constants in this interface
	 * @param dependencyCheck whether to perform a dependency check for object
	 *                        references in the bean instance (not applicable to autowiring a constructor,
	 *                        thus ignored there)
	 * @return the new bean instance
	 * @throws BeansException if instantiation or wiring failed
	 * @see #AUTOWIRE_NO
	 * @see #AUTOWIRE_BY_NAME
	 * @see #AUTOWIRE_BY_TYPE
	 * @see #AUTOWIRE_CONSTRUCTOR
	 * @see #AUTOWIRE_AUTODETECT
	 * @see #initializeBean
	 * @see #applyBeanPostProcessorsBeforeInitialization
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
	Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

	/**
	 * 通过名称/属性来自动注入指定bean的属性.
	 * 通过可以通过AUTOWIRE_NO来指定只执行初始化后的回调(比如:基于注解驱动的注入).
	 * 不会执行标准的bean后值处理器或者bean的进一步初始化方法.
	 * 基于这个目的,当前接口提供了细粒度话的操作方法.比如initializeBean方法,然而,
	 * InstantiationAwareBeanPostProcessor回调方法会被调用,来配置当前的实例.
	 * <p>
	 * <p>
	 * Autowire the bean properties of the given bean instance by name or type.
	 * Can also be invoked with {@code AUTOWIRE_NO} in order to just apply
	 * after-instantiation callbacks (e.g. for annotation-driven injection).
	 * <p>Does <i>not</i> apply standard {@link BeanPostProcessor BeanPostProcessors}
	 * callbacks or perform any further initialization of the bean. This interface
	 * offers distinct, fine-grained operations for those purposes, for example
	 * {@link #initializeBean}. However, {@link InstantiationAwareBeanPostProcessor}
	 * callbacks are applied, if applicable to the configuration of the instance.
	 *
	 * @param existingBean    the existing bean instance
	 * @param autowireMode    by name or type, using the constants in this interface
	 * @param dependencyCheck whether to perform a dependency check for object
	 *                        references in the bean instance
	 * @throws BeansException if wiring failed
	 * @see #AUTOWIRE_BY_NAME
	 * @see #AUTOWIRE_BY_TYPE
	 * @see #AUTOWIRE_NO
	 */
	void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
			throws BeansException;

	/**
	 * 使用指定名称的bean定义的属性值来填充指定的bean实例.
	 * 这个bean定义可以定义一个自包含的bean,重用它的属性值,或者只是定义用于现有的bean实例的属性值.
	 * 这个方法不会自动注入bean的属性;他仅仅只是应用显式定义的属性值/使用autowireBeanProperties来自动注入一个已有的bean实例.
	 * 注意,这个方法需要指定名称的bean定义.
	 * 不会执行标准的bean后值处理器或者bean的进一步初始化方法.
	 * 基于这个目的,当前接口提供了细粒度化的操作方法.比如initializeBean方法,然而,
	 * InstantiationAwareBeanPostProcessor回调方法会被调用,来配置当前的实例.
	 * Apply the property values of the bean definition with the given name to
	 * the given bean instance. The bean definition can either define a fully
	 * self-contained bean, reusing its property values, or just property values
	 * meant to be used for existing bean instances.
	 * <p>This method does <i>not</i> autowire bean properties; it just applies
	 * explicitly defined property values. Use the {@link #autowireBeanProperties}
	 * method to autowire an existing bean instance.
	 * <b>Note: This method requires a bean definition for the given name!</b>
	 * <p>Does <i>not</i> apply standard {@link BeanPostProcessor BeanPostProcessors}
	 * callbacks or perform any further initialization of the bean. This interface
	 * offers distinct, fine-grained operations for those purposes, for example
	 * {@link #initializeBean}. However, {@link InstantiationAwareBeanPostProcessor}
	 * callbacks are applied, if applicable to the configuration of the instance.
	 *
	 * @param existingBean the existing bean instance
	 * @param beanName     the name of the bean definition in the bean factory
	 *                     (a bean definition of that name has to be available)
	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException if there is no bean definition with the given name
	 * @throws BeansException                                                  if applying the property values failed
	 * @see #autowireBeanProperties
	 */
	void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;

	/**
	 * 使用工厂的类似与setBeanName和setBeanFactory之类的方法,以及所有的bean后置处理器来初始化一个原始bean.
	 * 请注意,bean工厂中不存在指定名称的bean定义,传入的bean名称仅仅用来回调,不会针对注册的bean定义进行检查.
	 * <p>
	 * Initialize the given raw bean, applying factory callbacks
	 * such as {@code setBeanName} and {@code setBeanFactory},
	 * also applying all bean post processors (including ones which
	 * might wrap the given raw bean).
	 * <p>Note that no bean definition of the given name has to exist
	 * in the bean factory. The passed-in bean name will simply be used
	 * for callbacks but not checked against the registered bean definitions.
	 *
	 * @param existingBean the existing bean instance
	 * @param beanName     the name of the bean, to be passed to it if necessary
	 *                     (only passed to {@link BeanPostProcessor BeanPostProcessors})
	 * @return the bean instance to use, either the original or a wrapped one
	 * @throws BeansException if the initialization failed
	 */
	Object initializeBean(Object existingBean, String beanName) throws BeansException;

	/**
	 * 调用给定实例bean后置处理器的postProcessBeforeInitialization方法,返回的bean实例可能是原始bean的包装bean.
	 * <p>
	 * Apply {@link BeanPostProcessor BeanPostProcessors} to the given existing bean
	 * instance, invoking their {@code postProcessBeforeInitialization} methods.
	 * The returned bean instance may be a wrapper around the original.
	 *
	 * @param existingBean the new bean instance
	 * @param beanName     the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one
	 * @throws BeansException if any post-processing failed
	 * @see BeanPostProcessor#postProcessBeforeInitialization
	 */
	Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException;

	/**
	 * 调用给定实例bean后置处理器的postProcessAfterInitialization方法,返回的bean实例可能是原始bean的包装bean.
	 * <p>
	 * Apply {@link BeanPostProcessor BeanPostProcessors} to the given existing bean
	 * instance, invoking their {@code postProcessAfterInitialization} methods.
	 * The returned bean instance may be a wrapper around the original.
	 *
	 * @param existingBean the new bean instance
	 * @param beanName     the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one
	 * @throws BeansException if any post-processing failed
	 * @see BeanPostProcessor#postProcessAfterInitialization
	 */
	Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException;

	/**
	 * 销毁给定的bean实例(通常是createBean方法创建的),通过DisposableBean协议以及注册DestructionAwareBeanPosetProcessor.
	 * 在销毁期间出现的任何异常都应该被捕获并记录,而不是传递给该方法的调用者.
	 * <p>
	 * Destroy the given bean instance (typically coming from {@link #createBean}),
	 * applying the {@link org.springframework.beans.factory.DisposableBean} contract as well as
	 * registered {@link DestructionAwareBeanPostProcessor DestructionAwareBeanPostProcessors}.
	 * <p>Any exception that arises during destruction should be caught
	 * and logged instead of propagated to the caller of this method.
	 *
	 * @param existingBean the bean instance to destroy
	 */
	void destroyBean(Object existingBean);


	//-------------------------------------------------------------------------
	// 解决注入点的委托方法.
	// Delegate methods for resolving injection points
	//-------------------------------------------------------------------------

	/**
	 * 解析唯一匹配指定对象类型的bean实例,如果有的话,就包含他的bean名称.
	 * 他实际上是getBean的变体,他保留了匹配实例的bean名称.
	 * <p>
	 * Resolve the bean instance that uniquely matches the given object type, if any,
	 * including its bean name.
	 * <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
	 * bean name of the matching instance.
	 *
	 * @param requiredType type the bean must match; can be an interface or superclass.
	 *                     {@code null} is disallowed.
	 * @return the bean name plus bean instance
	 * @throws NoSuchBeanDefinitionException   if no matching bean was found
	 * @throws NoUniqueBeanDefinitionException if more than one matching bean was found
	 * @throws BeansException                  if the bean could not be created
	 * @see #getBean(Class)
	 * @since 4.3.3
	 */
	<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;

	/**
	 * 根据当前工厂中定义的bean解析指定的依赖项.
	 * <p>
	 * Resolve the specified dependency against the beans defined in this factory.
	 *
	 * @param descriptor         the descriptor for the dependency (field/method/constructor)依赖项的描述符
	 * @param requestingBeanName the name of the bean which declares the given dependency
	 * @return the resolved object, or {@code null} if none found
	 * @throws NoSuchBeanDefinitionException   if no matching bean was found
	 * @throws NoUniqueBeanDefinitionException if more than one matching bean was found
	 * @throws BeansException                  if dependency resolution failed for any other reason
	 * @see #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
	 * @since 2.5
	 */
	@Nullable
	Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;

	/**
	 * 根据当前工厂中定义的bean解析指定的依赖项.
	 * <p>
	 * Resolve the specified dependency against the beans defined in this factory.
	 *
	 * @param descriptor         the descriptor for the dependency (field/method/constructor)
	 * @param requestingBeanName the name of the bean which declares the given dependency
	 * @param autowiredBeanNames a Set that all names of autowired beans (used for
	 *                           resolving the given dependency) are supposed to be added to
	 * @param typeConverter      the TypeConverter to use for populating arrays and collections
	 * @return the resolved object, or {@code null} if none found
	 * @throws NoSuchBeanDefinitionException   if no matching bean was found
	 * @throws NoUniqueBeanDefinitionException if more than one matching bean was found
	 * @throws BeansException                  if dependency resolution failed for any other reason
	 * @see DependencyDescriptor
	 * @since 2.5
	 */
	@Nullable
	Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
							 @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;

}
